"""
Case Type   : 故障&可靠性测试
Case Name   : 修复了启动扩容节点失败后，仍build关系的问题
Create At   : 2022/6/7
Owner       : n@ningyali
Description :
    1、准备扩容所用的XML文件
    2、构造部分节点启动失败情况，执行整个扩容流程
    3、根据日志打印观察扩容情况
Expect      :
    1、准备xml成功
    2、部分节点启动失败
    3、根据日志打印，发现对启动失败的节点未build
History     :
"""
import os
import re
import time
import unittest
from datetime import datetime

from yat.test import macro

from testcase.utils.ComThread import ComThread
from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH, RestartDbCluster
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger


class GsExpansion57(unittest.TestCase):
    nodes_tuple = ('PrimaryDbUser', 'Standby1DbUser', 'Standby2DbUser')

    @RestartDbCluster(*nodes_tuple)
    def setUp(self):
        self.sh = {'pri_root': CommonSH('PrimaryRoot'),
                   'pri_user': CommonSH(self.nodes_tuple[0]),
                   'sta1_root': CommonSH('Standby1Root'),
                   'sta1_user': CommonSH(self.nodes_tuple[1]),
                   'sta2_user': CommonSH(self.nodes_tuple[2])}
        self.node_num = self.sh['pri_user'].get_node_num()
        self.log = Logger()
        self.cons = Constant()
        self.com = Common()
        self.pri_hostname = self.com.get_sh_result(self.sh['pri_root'].node,
                                                   'hostname').strip()
        self.host_tuple = (self.sh.get("sta1_user").node.ssh_host,
                           self.sh.get("sta2_user").node.ssh_host)
        text = f'-----{os.path.basename(__file__)} start-----'
        self.log.info(text)

        text = '-----预置步骤: 获取数据目录所在磁盘名 expect: 成功-----'
        self.log.info(text)
        cmd = f"df -h {macro.DB_INSTANCE_PATH}|grep -v Filesystem|" \
            f"awk '{{{{print $1}}}}'"
        self.disk_name = self.com.get_sh_result(self.sh['sta1_root'].node,
                                                cmd).strip()
        self.log.info(self.disk_name)
        self.assertIn('/dev', self.disk_name)

        text = '----预置步骤: 一主两备减容两备，后续用例才能扩容 expect: 成功----'
        self.log.info(text)
        expect_msg = 'Success to drop the target nodes'
        shell_cmd = f'''source {macro.DB_ENV_PATH};
                    expect <<EOF
                    set timeout 300
                    spawn gs_dropnode -U {self.sh['pri_user'].node.ssh_user} \
                    -G {self.sh['pri_user'].node.ssh_user} \
                    -h {','.join(self.host_tuple)}
                    expect "*(yes/no)?" {{{{ send "yes\\n"; exp_continue }}}}
                    expect eof''' + "\nEOF\n"
        self.log.info(shell_cmd)
        res = self.com.get_sh_result(self.sh['pri_user'].node, shell_cmd)
        self.assertIn(expect_msg, res, f'执行失败: {text}')

        text = '---预置步骤: 数据库主机解压安装包，以免找不到扩容脚本 expect: 成功---'
        self.log.info(text)
        cmd = f'cd {os.path.dirname(macro.DB_SCRIPT_PATH)} && ' \
            f'tar -xf openGauss-Package-bak*.tar.gz && ' \
            f'ls {macro.DB_SCRIPT_PATH}|grep gs_sshexkey'
        self.log.info(cmd)
        res = self.com.get_sh_result(self.sh.get("pri_root").node, cmd)
        self.assertEqual(res, 'gs_sshexkey', f'执行失败: {text}')

        text = '----预置步骤: 建立root互信 expect: 成功----'
        self.log.info(text)
        ssh_cmd = f'cd {macro.DB_SCRIPT_PATH};' \
            f'echo "{self.sh.get("pri_root").node.ssh_host}\n' \
            f'{self.sh.get("sta1_user").node.ssh_host}\n' \
            f'{self.sh.get("sta2_user").node.ssh_host}" > hosts\n'
        ssh_cmd += f'''expect <<EOF
                            set timeout 300
                            spawn ./gs_sshexkey -f hosts
                            expect "*assword:"
                            send "{self.sh.get(
            "pri_root").node.ssh_password}\\n"
                            expect eof''' + "\nEOF\n"
        ssh_cmd += "source ~/.bashrc"
        self.log.info(ssh_cmd)
        res = self.com.get_sh_result(self.sh.get("pri_root").node, ssh_cmd)
        self.assertIn('Successfully created SSH trust', res, f'执行失败: {text}')

    def test_1(self):
        text = '----step1: 准备扩容所用的XML文件,延用安装时xml expect: 准备xml成功----'
        self.log.info(text)
        self.xml_path = macro.DB_XML_PATH

        text = '----step2: 构造部分节点启动失败情况，执行整个扩容流程 expect: 部分节点启动失败----'
        self.log.info(text)
        inject_cmd = f"rfile_full (diskname) values ({self.disk_name})"
        inject_res = self.com.cfe_inject(self.sh['sta1_root'].node, inject_cmd)
        self.log.info(inject_res)
        flg = "successful execution" in inject_res or \
              self.cons.FAILED_CONNECT_DB in inject_res
        self.assertTrue(flg, f'执行失败: {text}')

        text = '----step3: 备机扩容,根据日志打印观察扩容情况 ' \
               'expect: 根据日志打印，发现对启动失败的节点未build----'
        self.log.info(text)
        self.expansion_cmd = f'cd {macro.DB_SCRIPT_PATH};' \
            f'source {macro.DB_ENV_PATH}\n' \
            f'./gs_expansion -U {self.sh.get("pri_user").node.ssh_user} ' \
            f'-G {self.sh.get("pri_user").node.ssh_user} ' \
            f'-X {macro.DB_XML_PATH} ' \
            f'-h {",".join(self.host_tuple)} -L'
        self.log.info(self.expansion_cmd)
        res = self.com.get_sh_result(self.sh.get("pri_root").node,
                                     self.expansion_cmd)
        expect = f"Start to build standby {self.host_tuple[0]}.\n" \
            f"Failed to start {self.host_tuple[0]} as standby " \
            f"before building.\n" \
            f"Start to build standby {self.host_tuple[1]}."
        self.assertIn(expect, res, f'执行失败: {text}')
        regex_expect = f"Expansion results:.*{self.host_tuple[0]}:.*Failed" \
            f".*{self.host_tuple[1]}:.*Success.*Expansion Finish"
        regex_res = re.search(regex_expect, res, re.S)
        self.assertIsNotNone(regex_res, f'执行失败: {text}')

    def tearDown(self):
        text = '----run teardown----'
        self.log.info(text)

        text1 = '----后置操作: 恢复备机故障 expect: 故障恢复成功----'
        self.log.info(text1)
        clean_cmd = f"rfile_full where(diskname={self.disk_name})"
        clean_res = self.com.cfe_clean(self.sh['sta1_root'].node, clean_cmd)
        self.log.info(clean_res)

        text2 = '----后置操作: 备机扩容还原集群 expect: 备机扩容成功----'
        self.log.info(text2)
        self.expansion_cmd = self.expansion_cmd.replace(
            ',' + self.sh.get("sta2_user").node.ssh_host, '')
        self.log.info(self.expansion_cmd)
        res = self.com.get_sh_result(self.sh.get("pri_root").node,
                                     self.expansion_cmd)
        expansion_expect = 'Expansion results:.*:.*Success.*' \
                           'Expansion Finish.'
        regex_res = re.search(expansion_expect, res, re.S)

        text3 = '----检查集群状态是否正常----'
        self.log.info(text3)
        res2 = self.sh['pri_user'].getDbClusterStatus('detail')
        self.log.info(res2)

        self.assertIn("successful execution", clean_res, f'执行失败: {text1}')
        self.assertIsNotNone(regex_res, f'执行失败: {text2}')
        self.assertEqual(res2.count('Normal'), self.node_num + 1,
                         f'执行失败: {text3}')

        text = f'-----{os.path.basename(__file__)} end-----'
        self.log.info(text)
